from __future__ import annotations

"""
应用入口
-------
职责：
- 初始化 FastAPI 应用与中间件
- 在启动事件中初始化数据库与后台信号消费者
- 注册各个路由模块与中文 OpenAPI 标签说明

说明：
- `openapi_url` 放在 `/internal/openapi.json`，避免被网关/外部直接抓取
- CORS 默认全放开，生产建议按需收紧
"""

import logging

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy import select

from .config import get_settings
from .db import SessionLocal, init_db
from .models import RoleEnum, User
from .routers import ai, agent_strategies, audit, auth, broadcast, health, orders, risk_planner, rss, scripts, subscriptions, trading_pipeline, tv, users
from .security.auth import get_password_hash
from .services.mcp_session import mcp
from .services.agent_manager import agent_manager
from .services.rss_ingestor import rss_ingestor
from .services.signal_worker import signal_worker

logger = logging.getLogger(__name__)
settings = get_settings()

app = FastAPI(
    title="TradingView 控制平面",
    description=(
        "后端接口（Swagger 中文说明）：\n\n"
        "- auth：认证登录、刷新令牌、当前用户信息\n"
        "- scripts：策略管理（管理员）与市场可见策略（普通用户）\n"
        "- subscriptions：订阅策略（普通用户）\n"
        "- tv：TradingView Webhook 接入\n"
        "- users：账户与交易所凭据\n"
        "- orders/broadcast/audit/health：订单、广播、审计、健康检查\n"
        "- ai：AI 对话与工具调用\n"
        "- agent-strategies：Agent 策略配置与统一调度\n"
        "- risk-planner：风控规划器（动作契约）"
    ),
    openapi_tags=[
        {"name": "auth", "description": "登录、注册、刷新令牌与当前用户信息"},
        {"name": "scripts", "description": "策略管理（管理员）与策略市场（普通用户）"},
        {"name": "subscriptions", "description": "用户订阅策略管理"},
        {"name": "tradingview", "description": "TradingView Webhook 接入与最近信号"},
        {"name": "users", "description": "用户账户与交易所凭据管理"},
        {"name": "orders", "description": "订单相关接口"},
        {"name": "broadcast", "description": "广播下单"},
        {"name": "audit", "description": "审计日志查询"},
        {"name": "health", "description": "健康检查"},
        {"name": "ai", "description": "AI 对话与工具调用"},
        {"name": "agent-strategies", "description": "Agent 策略配置与统一调度"},
        {"name": "risk-planner", "description": "风控规划器：基于快照与风控配置输出交易动作规划"},
        {"name": "trading", "description": "交易执行管道：快照、决策、执行、对账、PnL计算与调度管理"},
    ],
    docs_url=settings.docs_url if settings.docs_enabled else None,
    redoc_url=settings.redoc_url if settings.docs_enabled else None,
    openapi_url=settings.openapi_url_path if settings.docs_enabled else None,
)

app.add_middleware(
    CORSMiddleware,
    allow_origins=["http://43.153.150.144:82"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)


@app.on_event("startup")
async def startup_event() -> None:
    await init_db()
    await signal_worker.start()
    await mcp.start()  # NEW
    await rss_ingestor.start()
    await agent_manager.start()
    
    # 重启自愈：恢复未完成的决策
    # from ..services.recovery import recover_pending_decisions
    # from ..db import SessionLocal
    # async with SessionLocal() as session:
    #     # 这里可以获取所有活跃的 run_id，然后恢复
    #     pass
    
    # 重启自愈：自动恢复调度器（如果配置了自动恢复）
    # 注意：默认不自动恢复，需要手动调用 /trading/scheduler/restore
    # 这样可以避免误启动，由管理员控制
    
    await _seed_admin()


@app.on_event("shutdown")
async def shutdown_event() -> None:
    await signal_worker.stop()
    await mcp.stop()  # NEW
    await rss_ingestor.stop()
    await agent_manager.stop()


async def _seed_admin() -> None:
    if not settings.admin_seed_enabled:
        logger.info("Admin seeding disabled via config")
        return
    async with SessionLocal() as session:
        stmt = select(User).where(User.email == settings.admin_seed_email)
        result = await session.execute(stmt)
        user = result.scalar_one_or_none()
        if user:
            return
        admin = User(
            email=settings.admin_seed_email,
            password_hash=get_password_hash(settings.admin_seed_password),
            role=RoleEnum.admin,
        )
        session.add(admin)
        await session.commit()
        logger.info("Seeded admin user %s", settings.admin_seed_email)


app.include_router(health.router)
app.include_router(auth.router)
app.include_router(scripts.router)
app.include_router(subscriptions.router)
app.include_router(orders.router)
app.include_router(tv.router)
app.include_router(broadcast.router)
app.include_router(broadcast.public_router)
app.include_router(audit.router)
app.include_router(users.router)
app.include_router(ai.router)
app.include_router(agent_strategies.router)
app.include_router(rss.router)
app.include_router(risk_planner.router)
app.include_router(trading_pipeline.router)  # NEW
